<?php

namespace maotool\async;

use maotool\core\facade\Config;
use maotool\core\serializer\closure\SerializableClosure;
use maotool\file\DirUtil;
use maotool\file\FileUtil;
use maotool\util\IdUtil;
use maotool\util\PathUtil;

/**
 * 异步运行函数
 */
class AsyncUtil
{

    /**
     * @var AsyncTask[]
     */
    public static $tasks = [];


    public function __construct()
    {

    }

    /**
     * 等待所有任务执行完毕
     * @return AsyncTask[]
     */
    public static function waitAll()
    {
        $async = true;
        $path = Config::get("framework.runtime.thread.path");
        while ($async) {
            $async = false;
            foreach (static::$tasks as &$task) {
                if ($task->getStatus() != 1) {
                    $resultDirPath = PathUtil::path($path, "result", substr($task->getUid(), 0, 2));
                    $resultFilePath = PathUtil::path($resultDirPath, substr($task->getUid(), 2) . ".thread");
                    if (FileUtil::exist($resultFilePath)) {
                        $task->setStatus(1);
                        $task->setResult(unserialize(FileUtil::read($resultFilePath)));
                        FileUtil::delete($resultFilePath);
                    } else {
                        $async = true;
                    }
                }
            }
        }
        return static::$tasks;
    }

    /**
     * 等待任意一个任务执行完毕
     * @return void
     */
    public static function waitAny()
    {

    }

    /**
     * @param $closure
     * @return AsyncTask
     */
    public static function run($closure)
    {
        $task = new AsyncTask();
        $task->setUid(md5(IdUtil::simpleUUID()));
        $task->setStatus(0);
        $path = Config::get("framework.runtime.thread.path");
        $dirPath = PathUtil::path($path, "task", substr($task->getUid(), 0, 2));
        $filePath = PathUtil::path($dirPath, substr($task->getUid(), 2) . ".thread");
        DirUtil::create($dirPath);
        $instance = new SerializableClosure($closure);
        $serialize = serialize($instance);
        FileUtil::write($filePath, $serialize);
        static::$tasks[] = $task;
        return $task;
    }

}